home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 2.0.1 / Experimental enhancements / MacApp Sizers / UArray.p < prev    next >
Text File  |  1990-11-08  |  6KB  |  265 lines

  1. { UArray.p }
  2. { Copyright © 1989-90 by Apple Computer, Inc. All rights reserved.}
  3.  
  4. UNIT UArray;
  5.  
  6. {    This unit implements a dynamically-sized object, called TIntegerArray, which is
  7.     an array of integers.  Each TIntegerArray can hold up to 32767 integers.
  8.  
  9.     Methods are provided for creating and initializing, as well as adding and
  10.     accessing elements of IntegerArrays.  No methods have been written for
  11.     deleting elements.
  12. }
  13.  
  14. INTERFACE
  15.  
  16.     USES
  17.         UObject, UFailure,
  18.         {Types,} Packages;                { PackIntf }
  19.  
  20.     CONST
  21.         kElementSize        = 2;        { size of one element (integer) }
  22.         kIncElements        = 2;        { number of elements to grow by }
  23.  
  24.         { Constants for NewInitializedArray’s zero parameter }
  25.         kZeroValue            = TRUE;        { initialize all elements to 0 }
  26.         kIntegerValue        = FALSE;    { initialize elements to 1, 2, 3, ... }
  27.  
  28.         { Constant for TIntegerArray.SortBy’s CompareItems function }
  29.         kFirstGreaterThanSecond    =  1;
  30.  
  31.     TYPE
  32.         TemplateArray        = ARRAY[1..MAXINT] OF INTEGER;
  33.         TemplateArrayPtr    = ^TemplateArray;
  34.  
  35.         TIntegerArray    = OBJECT (TObject)
  36.             fSize:                    INTEGER;        { the number of valid elements }
  37.             (* fIntegers:    dynamic ARRAY[1..n] of INTEGER *)
  38.  
  39.             PROCEDURE TIntegerArray.IArray(elements: INTEGER);
  40.             { Initialize the object to hold the specified number of elements,
  41.               and set fSize to 0. }
  42.  
  43.             PROCEDURE TIntegerArray.AddElement(value: INTEGER);
  44.             { Add an element to the array with the given value. }
  45.  
  46.             PROCEDURE TIntegerArray.AddUnique(value: INTEGER);
  47.             { Add the specified value only if it is not yet in the array }
  48.  
  49.             FUNCTION  TIntegerArray.At(index: INTEGER): INTEGER;
  50.             { Return the element at the given index. }
  51.  
  52.             PROCEDURE TIntegerArray.AtPut(index, value: INTEGER);
  53.             { Change the element at the given index to value. }
  54.  
  55.             FUNCTION  TIntegerArray.Contains(value: INTEGER): BOOLEAN;
  56.             { Return TRUE if the array contains the given value. }
  57.  
  58.             FUNCTION  TIntegerArray.GetSize: INTEGER;
  59.             { Return the number of valid elements. }
  60.  
  61.             PROCEDURE TIntegerArray.SortBy(
  62.                 FUNCTION CompareItems(index1, index2: INTEGER): INTEGER);
  63.             { Sort the elements using the given compare routine. }
  64.  
  65.             PROCEDURE TIntegerArray.Fields(PROCEDURE DoToField(fieldName: Str255;
  66.                                         fieldAddr: Ptr; fieldType: INTEGER)); OVERRIDE;
  67.             END;
  68.  
  69.  
  70.     FUNCTION NewIntegerArray(initialSize: INTEGER): TIntegerArray;
  71.     { Create a TIntegerArray big enough to hold initialSize elements }
  72.  
  73.     FUNCTION NewInitializedArray(elements: INTEGER; zero: BOOLEAN): TIntegerArray;
  74.     { Create a TIntegerArray with the specified number of elements, whose values are
  75.       initialized to either 0 (zero=T) or consecutive integers 1,2,3,... (zero=F). }
  76.  
  77. IMPLEMENTATION
  78.  
  79. {$S AInit}
  80.  
  81. FUNCTION NewIntegerArray(initialSize: INTEGER): TIntegerArray;
  82.  
  83.     VAR
  84.         intArray:        TIntegerArray;
  85.  
  86.     BEGIN
  87.     NEW(intArray);
  88.     FailNIL(intArray);
  89.     intArray.IArray(initialSize);
  90.     NewIntegerArray := intArray;
  91.     END;
  92.  
  93. FUNCTION NewInitializedArray(elements: INTEGER; zero: BOOLEAN): TIntegerArray;
  94.  
  95.     VAR
  96.         intArray:        TIntegerArray;
  97.         i:                INTEGER;
  98.  
  99.     BEGIN
  100.     intArray := NewIntegerArray(elements);
  101.     FOR i := 1 TO elements DO
  102.         IF zero
  103.             THEN intArray.AddElement(0)
  104.             ELSE intArray.AddElement(i);
  105.     NewInitializedArray := intArray;
  106.     END;
  107.  
  108.  
  109. PROCEDURE TIntegerArray.IArray(elements: INTEGER);
  110.  
  111.     VAR
  112.         newSize:        LONGINT;
  113.  
  114.     BEGIN
  115.     newSize := GetClassSize + (elements * kElementSize);
  116.     SetInstanceSize(newSize);
  117.     fSize := 0;
  118.     END;
  119.  
  120. {$S Array}
  121.  
  122. PROCEDURE TIntegerArray.AddElement(value: INTEGER);
  123.  
  124.     VAR
  125.         extraElements:    INTEGER;
  126.         mySize:            LONGINT;
  127.  
  128.     BEGIN
  129.     mySize := GetClassSize + (fSize * kElementSize);
  130.     extraElements := (GetInstanceSize - mySize) DIV kElementSize;
  131.     IF extraElements = 0 THEN BEGIN        { need to grow object to make room }
  132.         mySize := GetInstanceSize + (kIncElements * kElementSize);
  133.         SetInstanceSize(mySize);
  134.         END;
  135.  
  136.     fSize := fSize + 1;
  137.     AtPut(fSize, value);
  138.     END;
  139.  
  140. PROCEDURE TIntegerArray.AddUnique(value: INTEGER);
  141. { Add the specified value only if it is not yet in the array }
  142.  
  143.     BEGIN
  144.     IF NOT Contains(value) THEN
  145.         AddElement(value);
  146.     END;
  147.  
  148. FUNCTION TIntegerArray.At(index: INTEGER): INTEGER;
  149.  
  150.     VAR
  151.         pTemplateArray: TemplateArrayPtr;
  152.  
  153.     BEGIN
  154.     IF (index <= 0) | (index > fSize) THEN BEGIN
  155.         {$IFC qDebug}
  156.         ProgramBreak('TIntegerArray.At: index exceeds fSize');
  157.         {$ENDC}
  158.         At := 0;
  159.         END
  160.     ELSE BEGIN
  161.         pTemplateArray := TemplateArrayPtr(StripLong(@fSize)+SIZEOF(fSize));
  162.         At := pTemplateArray^[index];
  163.         END;
  164.     END;
  165.  
  166. PROCEDURE TIntegerArray.AtPut(index, value: INTEGER);
  167.  
  168.     VAR
  169.         pTemplateArray: TemplateArrayPtr;
  170.  
  171.     BEGIN
  172.     IF (index <= 0) | (index > fSize) THEN BEGIN
  173.         {$IFC qDebug}
  174.         ProgramBreak('TIntegerArray.AtPut: index exceeds fSize');
  175.         {$ENDC}
  176.         END
  177.     ELSE BEGIN
  178.         pTemplateArray := TemplateArrayPtr(StripLong(@fSize)+SIZEOF(fSize));
  179.         pTemplateArray^[index] := value;
  180.         END;
  181.     END;
  182.  
  183. {$S Array}
  184.  
  185. FUNCTION TIntegerArray.Contains(value: INTEGER): BOOLEAN;
  186.  
  187.     VAR
  188.         p:        TemplateArrayPtr;
  189.         i:        INTEGER;
  190.  
  191.     BEGIN
  192.     Contains := FALSE;
  193.     p := TemplateArrayPtr(StripLong(@fSize)+SIZEOF(fSize));
  194.     FOR i := 1 TO fSize DO
  195.         IF p^[i] = value THEN BEGIN
  196.             Contains := TRUE;
  197.             LEAVE;
  198.             END;
  199.     END;
  200.  
  201. FUNCTION TIntegerArray.GetSize: INTEGER;
  202.  
  203.     BEGIN
  204.     GetSize := fSize;
  205.     END;
  206.  
  207. {$S Array}
  208.  
  209. PROCEDURE TIntegerArray.SortBy(FUNCTION CompareItems(index1, index2: INTEGER): INTEGER);
  210. { Adapted from TList.SortBy; thanks, Steve! Nice variable names, too! }
  211. { NOTE: This doesn't work with a CompareItems Function that inserts or deletes elements. }
  212.  
  213.     VAR
  214.         i, j, h:            INTEGER;
  215.         v, item:            INTEGER;
  216.  
  217.     BEGIN
  218.     { Do a nice shell sort.  …For _really_ big lists this isn't fast enough }
  219.     {Initialize}
  220.     h := 1;
  221.     REPEAT
  222.         h := 3 * h + 1
  223.     UNTIL h > fSize;
  224.  
  225.     {Sort}
  226.     REPEAT
  227.         h := h DIV 3;
  228.         FOR i := h + 1 TO fSize DO BEGIN
  229.             v := At(i);
  230.             j := i;
  231.             item := At(j - h);
  232.             WHILE CompareItems(item, v) >= kFirstGreaterThanSecond DO BEGIN
  233.                 AtPut(j, item);
  234.                 j := j - h;
  235.                 IF j <= h THEN LEAVE;
  236.                 item := At(j - h);
  237.                 END;
  238.             AtPut(j, v);
  239.             END;
  240.     UNTIL h = 1;
  241.     END;
  242.     
  243. {$S AFields}
  244. PROCEDURE TIntegerArray.Fields(PROCEDURE DoToField(fieldName: Str255;
  245.                                     fieldAddr: Ptr; fieldType: INTEGER)); OVERRIDE;
  246.  
  247.     VAR
  248.         val, i:            INTEGER;
  249.         aString:        Str255;
  250.  
  251.     BEGIN
  252.     DoToField('TIntegerArray', NIL, bClass);
  253.     DoToField('fSize', @fSize, bInteger);
  254.  
  255.     FOR i := 1 to fSize DO BEGIN
  256.         NumToString(i, aString);
  257.         aString := Concat('.At[', aString, ']');
  258.         val := At(i);
  259.         DoToField(aString, @val, bInteger);
  260.         END;
  261.  
  262.     INHERITED Fields(DoToField);
  263.     END;
  264.  
  265. END.